; ------------------------------
; Base64 encoding program v1.0
; by Mateusz Tymek (c) 2004
;
; ------------------------------
; cmdln.asm
;   command line parsing
; ------------------------------


iglobal
; command line variables
cmdln:
  .argc   dd ?
  .argv   rd 0x10    ; 16 parameters limit
  .params rb 0x100

  .input_fname  dd ?
  .output_fname dd ?
  .switches     rd 8
  .out_buf      rb 0x50
endg


; strlen - returns length of given string
; from Fresh Standard Library
proc strlen, .str
        begin
        push    ebx
        mov     eax,[.str]
        mov     ebx,eax
  .scan:
        cmp     byte[eax],0
        lea     eax,[eax+1]
        jne     .scan
        sub     eax,ebx
        dec     eax         ; return value in eax
        pop     ebx
        return
endp

; strlen - returns length of given string
; from Fresh Standard Library
proc strcpy, .dest, .source
        begin
        push    esi edi eax ecx
        mov     edi,[.dest]
        mov     esi,[.source]
        stdcall strlen, esi
        mov     ecx,eax
        cld
        rep     movsb               ; copy strings
.finish:
        pop     ecx eax edi esi
        return
endp


; splits command line into single parameters
; (argv table)
proc parse_command_line, .cmdline
        begin
        push    eax ebx esi edi
        mov     [cmdln.argc],0
        mov     ebx,cmdln.argv
        mov     edi,cmdln.params
        mov     esi,[.cmdline]
     .load:
        mov     al,[esi]
        inc     esi
     .scan:
        cmp     al,0x20
        je      .load
        or      al,al
        jz      .finish
        inc     [cmdln.argc]
        mov     [ebx],edi
        add     ebx,4
        cmp     al,'"'
        je      .copy_quoted
     .copy_param:
        mov     [edi],al
        inc     edi
        mov     al,[esi]
        inc     esi
        cmp     al,0x20
        je      .param_copied
        or      al,al
        jz      .param_copied
        jmp     .copy_param
     .param_copied:
        mov     byte[edi],0
        inc     edi
        jmp     .scan
     .copy_quoted:
        mov     al,[esi]
        inc     esi
        cmp     al,'"'
        je      .end_quoted
        or      al,al
        jz      .param_copied
        mov     [edi],al
        inc     edi
        jmp     .copy_quoted
     .end_quoted:
        mov     al,[esi]
        inc     esi
        jmp     .param_copied
     .finish:
        pop     edi esi ebx eax
        return
endp


proc arrange_cmdline, .cmdline,.def_output_ext
        begin
        stdcall parse_command_line, [.cmdline]
        mov     esi,cmdln.switches
        xor     edx,edx
        xor     ecx,ecx

     .scan_param:
        inc     ecx
        cmp     ecx,[cmdln.argc]
        jae     .params_scanned
        mov     eax,[cmdln.argv+ecx*4]
        cmp     byte[eax],'-'
        je      .switch
        or      edx,edx
        jnz     .output_name
        mov     [cmdln.input_fname],eax
        inc     edx
        jmp     .scan_param
     .output_name:
        mov     [cmdln.output_fname],eax
        inc     edx
        jmp     .scan_param
     .switch:
        mov     [esi],eax
        add     esi,4
        jmp     .scan_param

     .params_scanned:
        cmp     [cmdln.argc],1
        je      .got_output_fname
        mov     dword[esi],0

        cmp     edx,2
        jae     .got_output_fname
        stdcall strcpy, cmdln.out_buf,[cmdln.input_fname]
        stdcall replace_ext, cmdln.out_buf,[.def_output_ext]
        mov     [cmdln.output_fname],cmdln.out_buf
     .got_output_fname:
        return
endp


; replaces extension of given filename to specified one.
; if ext is NULL, then the extension is removed
proc replace_ext, .filename,.ext
        begin
        mov     edi,[.filename]
        stdcall strlen, [.filename]
        add     edi,eax
        mov     ebx,edi
        dec     edi
    .scan:
        mov     al,[edi]
        cmp     al,'.'
        je      .got_extension
        cmp     al,'\'
        je      .append
        cmp     al,'/'
        je      .append
        cmp     al,':'
        je      .append
        or      al,al
        jz      .append
        dec     edi
        jmp     .scan

    .append:
        mov     edi,ebx
        mov     byte[edi],'.'
        inc     edi
        jmp     .get_new_ext

    .got_extension:
        inc     edi
    .get_new_ext:
        mov     esi,[.ext]
        or      esi,esi
        jz      .remove_ext
    .copy_ext:
        mov     al,[esi]
        mov     [edi],al
        inc     esi
        inc     edi
        or      al,al
        jnz     .copy_ext
    .finish:
        return
    .remove_ext:
        dec     edi
        xor     al,al
        mov     [edi],al
        jmp     .finish
endp


; replaces filename in given path
; if fname is NULL, then the file name is removed
proc replace_fname, .path,.fname
        begin
        mov     edi,[.path]
        stdcall strlen, [.path]
        or      eax,eax
        jz      .prepare_copy
        add     edi,eax
        mov     ebx,edi
        dec     edi
    .scan:
        mov     al,[edi]
        cmp     al,'\'
        je      .got_fname
        cmp     al,'/'
        je      .got_fname
        cmp     al,':'
        je      .got_fname
        or      al,al
        jz      .got_fname
        dec     edi
        jmp     .scan

    .got_fname:
        inc     edi
    .prepare_copy:
        mov     esi,[.fname]
    .copy_fname:
        mov     al,[esi]
        mov     [edi],al
        inc     esi
        inc     edi
        or      al,al
        jnz     .copy_fname
    .finish:
        return
endp


proc get_switch_w
        begin
        push    ebx edx
        mov     ebx,cmdln.switches
     .check:
        cmp     dword[ebx],0
        je      .false
        mov     edx,[ebx]

        cmp     word[edx],ax
        je      .true
        add     ebx,4
        jmp     .check
     .false:
        xor     eax,eax
        pop     edx ebx
        return
     .true:
        xor     eax,eax
        inc     eax
        pop     edx ebx
        return
endp